package com.nuoniu.sibanyun.service.crm.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.microsoft.schemas.office.visio.x2012.main.CellType;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.DateUtils;
import com.nuoniu.sibanyun.common.text.PinyinUtils;
import com.nuoniu.sibanyun.common.utils.SensitiveInfoUtils;
import com.nuoniu.sibanyun.entity.SysArea;
import com.nuoniu.sibanyun.entity.SysEmployee;
import com.nuoniu.sibanyun.entity.SysUser;
import com.nuoniu.sibanyun.entity.bo.ProcessSimpleBo;
import com.nuoniu.sibanyun.entity.crm.*;
import com.nuoniu.sibanyun.entity.dto.*;
import com.nuoniu.sibanyun.entity.erp.ErpNumberSet;
import com.nuoniu.sibanyun.entity.msg.SysMsg;
import com.nuoniu.sibanyun.entity.vo.CrmCustomerFinanceVo;
import com.nuoniu.sibanyun.entity.vo.SelectVo;
import com.nuoniu.sibanyun.entity.vo.SimpleCrmCustomerVo;
//import com.nuoniu.sibanyun.mapper.SysEmployeeMapper;
import com.nuoniu.sibanyun.mapper.SysUserMapper;
import com.nuoniu.sibanyun.mapper.crm.ApprovalProcessMapper;
import com.nuoniu.sibanyun.mapper.crm.CrmCustomerMapper;
import com.nuoniu.sibanyun.mapper.crm.CrmStrategyMapper;
import com.nuoniu.sibanyun.mapper.crm.*;
import com.nuoniu.sibanyun.mapper.erp.ErpNumberSetMapper;
import com.nuoniu.sibanyun.service.ISysAreaService;
import com.nuoniu.sibanyun.service.ISysUserService;
import com.nuoniu.sibanyun.service.crm.*;
import com.nuoniu.sibanyun.service.crm.call.ICrmCallTaskDetailService;
import com.nuoniu.sibanyun.service.erp.IErpNumberSetService;
import com.nuoniu.sibanyun.service.msg.ISysMsgService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import com.nuoniu.sibanyun.utils.ChineseCharToEnUtil;
import com.nuoniu.sibanyun.utils.ExcelUtils;
import com.twelvemonkeys.util.LinkedSet;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 客户基本信息 服务实现类
 * </p>
 *
 * @author baiqiang
 * @since 2020-06-15
 */
@Log4j2
@Service
public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCustomer> implements ICrmCustomerService {

    @Autowired
    private CrmCustomerMapper crmCustomerMapper;
    @Autowired
    private CrmStrategyMapper strategyMapper;
    @Autowired
    private ApprovalProcessMapper processMapper;
    @Autowired
    private IApprovalService approvalService;
    @Autowired
    private CrmLinkmanMapper linkmanMapper;
    @Autowired
    private CrmTouchMapper touchMapper;
    @Autowired
    private CrmConsigneeMapper consigneeMapper;
    @Autowired
    private CrmFilesMapper filesMapper;
    @Autowired
    private CrmFinanceInfoMapper financeInfoMapper;
    @Autowired
    private CrmRequirementMapper requirementMapper;
    @Autowired
    private CrmQuotedPriceMapper quotedPriceMapper;
    @Autowired
    private CrmDefineFieldMapper defineFieldMapper;
    @Autowired
    private ICrmLinkmanService linkmanService;
    @Autowired
    private ICrmHistoryRecordService crmHistoryRecordService;
    @Autowired
    private CrmHistoryRecordMapper historyRecordMapper;
    @Autowired
    private ICrmStrategyService crmStrategyService;
    @Autowired
    private ISysAreaService areaService;
//    @Autowired
//    private SysEmployeeMapper employeeMapper;
    @Autowired
    private ISysAreaService sysAreaService;
    @Autowired
    private ICrmFinanceInfoService crmFinanceInfoService;
    @Autowired
    private ICrmDefineFieldService defineFieldService;
    @Autowired
    private ICrmGoodsService goodsService;
    @Autowired
    private IErpNumberSetService numberSetService;
    @Autowired
    private ErpNumberSetMapper numberSetMapper;
    @Autowired
    private ISysMsgService msgService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    @Lazy
    private ISysUserService userService;
    @Autowired
    @Lazy
    private ICrmCallTaskDetailService callTaskDetailService;

    @Override
    public Page<HashMap<String, Object>> CrmDynamicPage(DynamicDto dynamicDto) {
        log.debug("客户动态查询开始");
        long s = System.currentTimeMillis();
        UserInfo userInfo = UserThreadLocal.get();
        Page<HashMap<String, Object>> hashMapPage = new Page<>();
        List<DynamicConditionDto> dtos = dynamicDto.getDtos();
        List<DynamicConditionDto> joinTableConditions = dynamicDto.getJoinTableConditions();
        Page page = dynamicDto.getPage();
        dynamicDto.setUserId(userInfo.getUserId());
        if(null == dtos || dtos.size() == 0) return hashMapPage;
        //
        Optional<DynamicConditionDto> optional = dtos.stream().filter(f -> f.getCode().equals("areaId") && StringUtils.isNotBlank(f.getValue())).findFirst();
        if (optional.isPresent()){
            DynamicConditionDto dynamicConditionDto = optional.get();
            String value = dynamicConditionDto.getValue();
            SysArea area = sysAreaService.getById(value);
            if( null != area ){
                dynamicConditionDto.setValue(area.getAreaCode().toString());
            }
        }
        String crmType = dynamicDto.getCrmType();
        HashMap<String,Object> paramMap = new HashMap<>();
        //生成 动态参数Map
        List<DynamicConditionDto> dtoList = new ArrayList<>();
        dtoList.addAll(dtos);
        if(null != joinTableConditions){
            dtoList.addAll(joinTableConditions);
        }
        getDynamicParamMap(paramMap,dtoList);
        hashMapPage = baseMapper.CrmDynamicPage(dynamicDto,paramMap,page);
        if(crmType != null) {
            //潜在策略释放
            //crmAsyncServer.crmStrategy(userInfo);
            //线索客户
            if(crmType.contains("0")){
                //检查是否开启 线索客户 脱敏策略 1可见 0 不可见
                CrmStrategy crm9 = crmStrategyService.getStrategyByCode("crm_9", userInfo.getCompanyId());
                if(null != crm9 && crm9.getStrategyVal().equals("0") ){
//                    replaceStrByCode(hashMapPage,"mobile","*",3,7);
                    replaceAllStrByCode(hashMapPage,"mobile,officePhone","****");
                }
            }
        }

        long e = System.currentTimeMillis();
        long sub = e - s;
        log.debug("客户动态查询耗时{}毫秒",sub);
        return hashMapPage;
    }

    @Override
    public CrmCustomer getByName(String name) {
        if(StringUtils.isBlank(name)){
            return null;
        }
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("crm_name",name);
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.eq("status",0);
        queryWrapper.last("LIMIT 1");
        CrmCustomer one = getOne(queryWrapper,false);
        return one;
    }

    @Override
    public String checkCrmName(List<DynamicConditionDto> dtos) {
        String message = "";
        Optional<DynamicConditionDto> dynamicConditionDtoOptional = dtos.stream().filter(f -> StringUtils.isNotBlank(f.getCode()) && f.getCode().equals("crmName")).findFirst();
        if (dynamicConditionDtoOptional.isPresent()){
            DynamicConditionDto dto = dynamicConditionDtoOptional.get();
            String val = dto.getValue();
            CrmCustomer crmCustomer = getByName(val);
            if(crmCustomer != null) {
                message = checkRecord(1,crmCustomer);
            }
        }
        return message;
    }

    /**
     * 校验 记录存在情况
     * @param checkType
     * @param crmCustomer
     * @return
     */
    public String checkRecord(Integer checkType, CrmCustomer crmCustomer){
        UserInfo userInfo = UserThreadLocal.get();
        String message = "";
            if(null != crmCustomer){
                String name = crmCustomer.getCrmName();
                Integer crmType = crmCustomer.getCrmType();
                switch (checkType){
                    //校验  客户
                    case 1:
                        Boolean isCustomer = crmCustomer.getIsCustomer();
                        if(isCustomer){
                            switch (crmType){
                                case 0: message += "单位："+name+"， 在公海线索中";
                                if(crmCustomer.getIsTasking()){
                                    message +=";外呼任务中";
                                }
                                break;
                                case 1:{
                                    if(!userInfo.getUserId().equals(crmCustomer.getCollarUserId())){
                                        message += "客户："+name+"， 在潜在客户中， 但领用人不是你";break;
                                    }else{
                                        message += "客户："+name+"， 在潜在客户中";break;
                                    }
                                }
                                case 2:{
                                    if(!userInfo.getUserId().equals(crmCustomer.getCollarUserId())){
                                        message += "客户："+name+"， 在成交客户中，但领用人不是你";break;
                                    }else {
                                        message +=  "客户："+name+"， 在成交客户中";break;
                                    }
                                }
                            }
                        }else {
                            message += "客户："+name+"， 不在客户记录中";
                        }
                        break;
                    //校验  供应商
                    case 2:
                        Boolean isSupplier = crmCustomer.getIsSupplier();
                        if(!isSupplier){
                            message += "供应商："+name+"， 不在供应商记录中";
                        }
                        break;
                }

            }
        return message;
    }


    @Override
    public Page<SelectVo> pageForSelect(Page page, CrmCustomerSearchDto crmCustomerSearchDto) {
        String companyTypeSql = "";
        String companyType = crmCustomerSearchDto.getCompanyType();
        if (com.nuoniu.sibanyun.common.lang.StringUtils.isNotBlank(companyType)) {
            boolean isFirst = true;
            if (companyType.contains("isCustomer")) {
                companyTypeSql += " crm.is_customer = 1 ";
                isFirst = false;
            }
            if (companyType.contains("isSupplier")) {
                if (!isFirst) {
                    companyTypeSql += " OR ";
                }
                companyTypeSql += " crm.is_supplier = 1 ";
            }
            if (companyType.contains("isOther")) {
                if (!isFirst) {
                    companyTypeSql += " OR ";
                }
                companyTypeSql += " crm.is_other = 1 ";
            }
            companyTypeSql = "(" + companyTypeSql + ")";
        }
        Page<SelectVo> selectVoPage = baseMapper.pageForSelect(page, crmCustomerSearchDto,companyTypeSql);
//        if(selectVoPage.getSize() == 0){
//            if(StringUtils.isNotBlank(crmCustomerSearchDto.getKeyWord())){
//                CrmCustomer crmCustomer = getByName(crmCustomerSearchDto.getKeyWord());
//                String message = checkRecord(1,crmCustomer);
//                if (StringUtils.isNotBlank(message)){
//                    throw new NuoNiuException(message);
//                }
//            }
//        }
        return selectVoPage;
    }

    @Override
    public Page<SimpleCrmCustomerVo> pageForVoucher(Page page, CrmCustomerSearchDto crmCustomerSearchDto) {
        UserInfo userInfo = UserThreadLocal.get();
        String companyType = crmCustomerSearchDto.getCompanyType();
        String companyTypeSql = "";
        if (com.nuoniu.sibanyun.common.lang.StringUtils.isNotBlank(companyType)) {
            boolean isFirst = true;
            if (companyType.contains("isCustomer")) {
                companyTypeSql += " crm.is_customer = 1 ";
                isFirst = false;
            }
            if (companyType.contains("isSupplier")) {
                if (!isFirst) {
                    companyTypeSql += " OR ";
                }
                companyTypeSql += " crm.is_supplier = 1 ";
            }
            if (companyType.contains("isOther")) {
                if (!isFirst) {
                    companyTypeSql += " OR ";
                }
                companyTypeSql += " crm.is_other = 1 ";
            }
            companyTypeSql = "(" + companyTypeSql + ")";
        }
        Page<SimpleCrmCustomerVo> pageForVoucher = baseMapper.pageForVoucher(page,userInfo.getCompanyId(), crmCustomerSearchDto,companyTypeSql);
        return pageForVoucher;
    }

    /**
     * 生成动态参数
     * @param paramMap
     * @param dtos
     */
    private void getDynamicParamMap(HashMap<String,Object> paramMap,List<DynamicConditionDto> dtos){
        dtos.stream().filter(f->StringUtils.isNotBlank(f.getValue()) || (null != f.getRangDateVal() && f.getRangDateVal().length == 2) ).forEach(item->{
            Integer dataType = item.getDataType();
            String code = "";
            if(1 == dataType || 2 == dataType){
                code = item.getCode();
            }else if(3 == dataType || 4 == dataType){
                code = item.getParentCode();
            }
            if(StringUtils.isNotBlank(item.getValue())){
                paramMap.put(code,item.getValue());
            }else{
                Object[] rangDateVal = item.getRangDateVal();
                ArrayList rangDate = (ArrayList)rangDateVal[1];
                String startDate = String.valueOf(rangDate.get(0));
                String endDate =String.valueOf(rangDate.get(1));
                paramMap.put(code+ "_endDate",endDate);
                paramMap.put(code+ "_startDate",startDate);
            }
        });
    }

    /**
     *
     * @param hashMapPage
     * @param codes
     * @param overChar
     */
    private void replaceAllStrByCode(Page<HashMap<String, Object>> hashMapPage,String codes,String overChar){
        List<HashMap<String, Object>> records = hashMapPage.getRecords();
        if(StringUtils.isBlank(codes) || StringUtils.isBlank(overChar))return;
        String[] split = codes.split(",");
        records.stream().forEach(f->{
            for (int i = 0; i < split.length ; i++){
                String code = split[i];
                Object o = f.get(code);
                if(null != o){
                    f.put(code,overChar);
                }
            }
        });
    }

    /**
     * 替换 指定 Code 字段的工具类
     * @param hashMapPage
     * @param code
     * @param overChar
     * @param strat
     * @param end
     */
    private void replaceStrByCode(Page<HashMap<String, Object>> hashMapPage,String code,String overChar,int strat,int end){
        List<HashMap<String, Object>> records = hashMapPage.getRecords();
        if(StringUtils.isBlank(code))return;
        records.stream().forEach(f->{
            Object o = f.get(code);
            if(null != o){
                String s = o.toString();
                String resultStr = SensitiveInfoUtils.mobilePhoneOverlay(s, overChar, strat, end);
                f.put(code,resultStr);
            }
        });
    }
    @Override
    public CrmCustomer findById(Integer id) {
        return baseMapper.findById(id);
    }

    @Override
    public Integer getCrmCustomerStatus(Integer id) {
        return baseMapper.getCrmCustomerStatus(id);
    }

    @Override
    public List<String> getExcelFiled(MultipartFile file) {
        boolean isExcel2003 = true;
        List<String> fileds = new ArrayList<>();
        if (file.getOriginalFilename().matches("^.+\\.(?i)(xlsx)$")) {
            isExcel2003 = false;
        }
        try {
            InputStream is = file.getInputStream();
            Workbook wb = null;
            if (isExcel2003) {
                wb = new HSSFWorkbook(is);
            } else {
                wb = new XSSFWorkbook(is);
            }

            Sheet sheet = wb.getSheetAt(0);
            Row row = sheet.getRow(0);
            int cellsLength = row.getPhysicalNumberOfCells();
            for (int i = 0; i < cellsLength; i++) {
                Cell c = row.getCell(i);
                if(c == null){
                    continue;
                }
                //获取表头字段名
                String filed = c.getStringCellValue();
                fileds.add(filed);
            }
            return fileds;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取Excel表头
     * @param file
     * @param source
     * @return
     */
    @Override
    public HashMap<String, Object> getExcelFiledFromCompanyType(MultipartFile file, String source) {
        UserInfo userInfo = UserThreadLocal.get();
        HashMap data = new HashMap();
        List<String> excelFiled = getExcelFiled(file);
        data.put("excelFiled", excelFiled);
        if("crm".equals(source)){
            List<Map<String, String>> crmFiled = getCrmImportFiled();
            data.put("crmFiled", crmFiled);
        }else{
            String  ex = "crmNo,createUserId,createDate,status";
            //TODO 其他 数据来源 可修改ex（排除字段）
            List<Map<String, String>> vendorFiled = defineFieldMapper.getCrmImportFiledBySource(userInfo.getCompanyId(),source);
            vendorFiled = vendorFiled.stream().filter(f->!ex.contains(f.get("key").split("_")[1])).collect(Collectors.toList());
            data.put("crmFiled", vendorFiled);
        }
        return data;
    }

    @Override
    public CrmCustomer findByName(Integer companyId, String crmName) {
        return crmCustomerMapper.findByName(companyId, crmName);
    }

    @Override
    public String getCustomerNo(Integer companyId) {
        ErpNumberSet numberSet = numberSetMapper.getByCode("Customer", companyId, 0);
        if(numberSet == null) {
            return "";
        }

        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getNewestCode(companyId, dateStr);
        return numberSetService.getCode(numberSet, code);
    }

    @Override
    public void updateStatus(String ids, Integer status) {
        UserInfo userInfo = UserThreadLocal.get();
        String[] idArr = ids.split(",");
        for(String id : idArr) {
            UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper<>();
            CrmCustomer customer = this.getById(id);
            if(null != customer.getIsSupplier() && !customer.getIsSupplier()) {
                updateWrapper.set("status", 2);
            }

            updateWrapper.set("is_customer", 0);
            updateWrapper.eq("company_id", userInfo.getCompanyId());
            updateWrapper.eq("id", id);
            update(updateWrapper);
        }
    }

    @Override
    public void exportData(DynamicDto dynamicDto, HttpServletResponse response) {
        String companyType = dynamicDto.getCompanyType();
        String fileName = "客户资料" + DateUtils.formatDate(new Date(), "yyyyMMdd") + ".xls";
        if(companyType.equals("isSupplier")){
            fileName = "供应商资料" + DateUtils.formatDate(new Date(), "yyyyMMdd") + ".xls";
        }

        UserInfo userInfo = UserThreadLocal.get();
        dynamicDto.setUserId(userInfo.getUserId());
        dynamicDto.setPage(new Page(1, -1));
        List<CrmExcelDto> crmDataList;
        if(dynamicDto.getCrmIds() != null && dynamicDto.getCrmIds().length > 0) {
            crmDataList = crmCustomerMapper.getCustomerList(StringUtils.join(dynamicDto.getCrmIds(), ","));
        }else {
            HashMap<String,Object> paramMap = new HashMap<>();
            //生成 动态参数Map
            getDynamicParamMap(paramMap,dynamicDto.getDtos());
            Page<CrmExcelDto> crmPage = crmCustomerMapper.crmListPage(dynamicDto,paramMap, dynamicDto.getPage());//获取列表
            crmDataList = crmPage.getRecords();
        }

        if(companyType.equals("isCustomer")){
            for(CrmExcelDto crmExcelDto : crmDataList) {
                List<Map> linkMans = linkmanMapper.getByCrmId(crmExcelDto.getId());
                crmExcelDto.setLinkMans(linkMans);
            }
        }

        ExcelUtils.exportCompany(dynamicDto, crmDataList, fileName, response);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String receive(String remarks, List<Integer> ids) {
        if(ids.size() > 500)throw new NuoNiuException("一次领用数量不得超过500");
        long time = System.currentTimeMillis();
        List<CrmCustomer> crmCustomerList = new ArrayList<>();
        List<ProcessSimpleBo> processSimpleBoList = new ArrayList<>();

        String message = "领用成功！";
        UserInfo userInfo = UserThreadLocal.get();
        // 潜在客户数量根据策略判断是否可新增
        CrmStrategy strategy = strategyMapper.getStrategyByCode("crm_1", userInfo.getCompanyId());
        Integer num = 0;
        if (strategy != null && StringUtils.isNotEmpty(strategy.getStrategyVal())) {
            num = Integer.parseInt(strategy.getStrategyVal());
        }

        int n = crmCustomerMapper.getReceiveCount(userInfo.getUserId());
        // 拥有潜在客户是否大于策略值
        if (n + ids.size() > num) {
            Integer str = num - n;
            if ((num - n) < 0) {
                str = 0;
            }
            throw new  NuoNiuException("领用超过潜在客户上限，您还能领用客户数量：" + str);
        }

        Boolean approval = true; // 领用是否需要审批 客户策略中配置
        strategy = strategyMapper.getStrategyByCode("crm_6", userInfo.getCompanyId());
        if ("0".equals(strategy.getStrategyVal())) {
            approval = false;
        }else{
            message = "领用成功，请等待审核！";
        }

        strategy = strategyMapper.getStrategyByCode("crm_4", userInfo.getCompanyId());
        String isUse = strategy.getStrategyVal();
        String crmName = "";
        List<ApprovalProcess> list = processMapper.getProcessByType(1, userInfo.getCompanyId());


        for (Integer id : ids) {
            CrmCustomer customer = getById(id);
            CrmHistoryRecord record = historyRecordMapper.getRecord(id, userInfo.getUserId(), 2);
            if(record != null && !isUse.equals("0") && userInfo.getUserId().equals(customer.getReleaseUserId())) { //判断当前是否能被领用
                int day = (int) ((LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() - record.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli()) / (1000*3600*24));
                if(day < Integer.parseInt(isUse)) {
                    crmName += customer.getCrmName() + " ";
                    throw new  NuoNiuException("客户名为：" + crmName + "领用失败，由本人释放后，" + isUse + "天内不能领用");
                }
            }

            if(customer.getApprovalType() != null && customer.getApprovalType() == 2) { //审核中的客户不能领用
                throw new  NuoNiuException("客户名为：" + customer.getCrmName() + "领用失败，正在审核中！");
            }

            // 记录领用人
            customer.setCollarUserId(userInfo.getUserId());
            customer.setCollarUserName(userInfo.getRealName());
            // 记录领用时间
            customer.setCollarTime(LocalDateTime.now());
            customer.setOfficeId(userInfo.getOfficeId());
            customer.setOfficeName(userInfo.getOfficeName());

            if (approval) { //加入审批流程
                customer.setApprovalType(2);
                // 写申请记录
                if (list.size() == 0) {
                    throw new  NuoNiuException("未配置客户审批流程！");
                }
                ApprovalProcess approvalProcess = list.get(0);
//                approvalService.startProcess(approvalProcess.getId(), customer.getId(), "来自" + userInfo.getRealName() + "的客户审批(" + customer.getCrmName() + ")",
//                        approvalProcess.getApprovalUserId(), approvalProcess.getProcessType(), approvalProcess.getApprovalMode(), list.size());

                ProcessSimpleBo processSimpleBo = new ProcessSimpleBo();
                processSimpleBo.setApprovalProcessId(approvalProcess.getId());
                processSimpleBo.setSourceId(customer.getId());
                processSimpleBo.setContent("来自" + userInfo.getRealName() + "的客户审批(" + customer.getCrmName() + ")");
                processSimpleBo.setApprovalUserId( approvalProcess.getApprovalUserId());
                processSimpleBo.setProcessType( approvalProcess.getProcessType());
                processSimpleBo.setApprovalMode(approvalProcess.getApprovalMode());
                processSimpleBo.setSize(list.size());
                processSimpleBoList.add(processSimpleBo);

            } else {
                // 记录领用时间
                customer.setCrmType(1);
            }
            crmCustomerList.add(customer);
//            updateById(customer);
        }
        // 批量 加入审批流程
        approvalService.batchStartProcess(processSimpleBoList);
        // 批量 更新
        updateBatchById(crmCustomerList);
        long useTime = System.currentTimeMillis() - time;
        log.debug("领用{}个客户数据，耗时{}毫秒",ids.size(),useTime);
        return message;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveShare(CrmCustomer crmCustomer, Long... ids) {
        if (ids.length == 0)throw new NuoNiuException("请选择客户");
        List<Long> longIds = Arrays.asList(ids);
        if(  !checkCustomerCollarUser(longIds) ){
            throw new NuoNiuException("不是领用人,不能成交");
        }
        CrmCustomer updateCrmCustomer = new CrmCustomer();
        updateCrmCustomer.setShareEnd(crmCustomer.getShareEnd());
        updateCrmCustomer.setShareMenu(crmCustomer.getShareMenu());
        if (StringUtils.isBlank(crmCustomer.getShareUserId())) {
            updateCrmCustomer.setShareType(0);// 设置共享状态
        } else {
            updateCrmCustomer.setShareType(1);// 设置共享状态
        }
        updateCrmCustomer.setShareTime(crmCustomer.getShareTime());
        updateCrmCustomer.setShareUserId(crmCustomer.getShareUserId());
        updateCrmCustomer.setShareUserName(crmCustomer.getShareUserName());
        UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper();
        updateWrapper.in("id",ids);
        update(updateCrmCustomer,updateWrapper);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void release(List<Integer> ids) {
        if(ids.size() > 500)throw new NuoNiuException("一次释放数量不得超过500");
        long time = System.currentTimeMillis();
        UserInfo userInfo = UserThreadLocal.get();
        List<CrmHistoryRecord> crmHistoryRecordList = new ArrayList<>();
        List<CrmCustomer> crmCustomerList = new ArrayList<>();
        Integer companySysRoleIdByCompanyId = goodsService.getCompanySysRoleIdByCompanyId();
        for (Integer id : ids) {
            QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id","crm_type","crm_name","company_id","collar_time","collar_user_id","collar_user_name");
            queryWrapper.eq("id",id);
            queryWrapper.last("LIMIT 1");
            CrmCustomer customer = getOne(queryWrapper);
            Integer crmType = customer.getCrmType();
            if( !(null != crmType && crmType == 1) ) throw new NuoNiuException(customer.getCrmName() + "：不是潜在客户，不能释放");
            if(!customer.getCompanyId().equals(userInfo.getCompanyId()) || (!customer.getCollarUserId().equals(userInfo.getUserId()) && !userInfo.getRoleIds().contains(companySysRoleIdByCompanyId))) {
                throw new NuoNiuException("不是领用人，不能释放");
            }
            // 记录领用时间
            customer.setCrmType(0);
            customer.setLastCollarTime(customer.getCollarTime());
            customer.setLastCollarUserId(customer.getCollarUserId());
            customer.setLastCollarUserName(customer.getCollarUserName());
            // 客户释放取消共享
            customer.setShareType(0);
            customer.setReleaseUserId(userInfo.getUserId());
            customer.setReleaseUserName(userInfo.getRealName());
            customer.setReleaseTime(LocalDateTime.now());// 记录释放时间
            crmCustomerList.add(customer);
//            UpdateWrapper<CrmCustomer> wrapper = new UpdateWrapper();
//            wrapper.set("collar_time", null);
//            wrapper.set("collar_user_id", null);
//            wrapper.eq("id", id);
//            update(customer, wrapper);
            // 保存释放操作记录
            CrmHistoryRecord historyRecord = new CrmHistoryRecord();
            historyRecord.setCrmId(customer.getId().intValue());
            historyRecord.setCrmName(customer.getCrmName());
            historyRecord.setUserId(userInfo.getUserId());
            crmHistoryRecordList.add(historyRecord);
            if(crmHistoryRecordList.size() == 100){
                baseMapper.batchReleaseCustomer(crmCustomerList);
                crmHistoryRecordList= new ArrayList<>();
            }
        }
        if (crmHistoryRecordList.size() > 0){
            baseMapper.batchReleaseCustomer(crmCustomerList);
        }
        crmHistoryRecordService.saveBatch(crmHistoryRecordList);
        long useTime = System.currentTimeMillis() - time;
        log.debug("释放{}个客户数据，耗时{}毫秒",ids.size(),useTime);
    }

    @Override
    public boolean checkCustomerCollarUser(Collection<?> ids) {
        if( null == ids || ids.size() == 0)return false;
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("collar_user_id",userInfo.getUserId());
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.in("id",ids);
        int count = count(queryWrapper);
        return count == ids.size();
    }

    @Override
    public boolean checkCustomerType(Collection<?> ids,Integer crmType) {
        if( null == ids || ids.size() == 0)return false;
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("crm_type",crmType);
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.in("id",ids);
        int count = count(queryWrapper);
        return count == ids.size();
    }

    /**
     * 成交客户
     * @author 白强
     * @date 20210911
     */
    @Override
    public void dealSave(List<Integer> ids) {
        Integer companySysRoleIdByCompanyId = goodsService.getCompanySysRoleIdByCompanyId();
        UserInfo userInfo = UserThreadLocal.get();
        if(!checkCustomerType(ids,1))throw new NuoNiuException("不是潜在客户，不能成交");
        // 管理员无限制
        if(!userInfo.getRoleIds().contains(companySysRoleIdByCompanyId)){
            // 查询 是否 不是我自己的客户
           if(  !checkCustomerCollarUser(ids) ){
               throw new NuoNiuException("不是领用人,不能成交");
           }
        }
        UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",ids);
        /** 成交后，设置为 财务可见 20220119 白强 */
        updateWrapper.set("is_finance",1);
        updateWrapper.set("crm_type",2);
        updateWrapper.set("share_type",0);
        updateWrapper.set("share_menu","");
        updateWrapper.set("share_user_id","");
        updateWrapper.set("share_user_name","");
        update(updateWrapper);

    }

    /**
     * 成交客户 退回
     * @param ids
     */
    @Override
    public void potentialSave(List<Integer> ids) {
        UserInfo userInfo = UserThreadLocal.get();
        if(!checkCustomerType(ids,2))throw new NuoNiuException("不是成交客户，不能退回");
        Integer companySysRoleIdByCompanyId = goodsService.getCompanySysRoleIdByCompanyId();
        // 管理员无限制
        if(!userInfo.getRoleIds().contains(companySysRoleIdByCompanyId)){
            // 查询 是否 不是我自己的客户
            if(  !checkCustomerCollarUser(ids) ){
                throw new NuoNiuException("不是领用人,不能成交");
            }
        }
        UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper();
        updateWrapper.in("id",ids);
        updateWrapper.set("crm_type",1);
        updateWrapper.set("update_user_id",userInfo.getUserId());
        updateWrapper.set("update_user_name",userInfo.getRealName());
        update(updateWrapper);
    }

    /**
     * 分配客户
     * @author 小啊刚
     * @date 2020/6/20
     */
    @Override
    public void distributionSave(Integer type, Integer collarUserId, String collarUserName, String ids) {
        UserInfo userInfo = UserThreadLocal.get();
        int num = 10;
        // 潜在客户数量根据策略判断是否可新增
        if (type == 1) {
            CrmStrategy strategy = strategyMapper.getStrategyByCode("crm_1", userInfo.getCompanyId());
            if (StringUtils.isNotBlank(strategy.getStrategyVal())) {
                num = Integer.parseInt(strategy.getStrategyVal());
            }
            int n = crmCustomerMapper.getReceiveCount(collarUserId);
            n = n + ids.split(",").length;
            // 拥有潜在客户是否大于策略值
            if (n > num) {
                throw new NuoNiuException("该用户潜在客户数量到达上限，无法分配！");
            }
        }

        SysUser employee = sysUserMapper.getByUser(collarUserId.longValue());
        List<CrmCustomer> updateCrmCustomerList = new ArrayList<>();
        for (String id : ids.split(",")) {
            CrmCustomer customer = getById(id);
            CrmCustomer newCrmCustomer = new CrmCustomer();
            newCrmCustomer.setId(customer.getId());
            // 记录领用时间
            newCrmCustomer.setCrmType(type);
            newCrmCustomer.setCollarTime(LocalDateTime.now());
            newCrmCustomer.setCollarUserId(collarUserId);
            newCrmCustomer.setCollarUserName(collarUserName);
            newCrmCustomer.setOfficeId(employee.getOfficeId().intValue());
            newCrmCustomer.setOfficeName(employee.getOfficeName());
            updateCrmCustomerList.add(newCrmCustomer);
        }
        updateBatchById(updateCrmCustomerList);
        // 发送通知
        //msgInnerService.sendMsg("客户分配消息", UserUtils.getUser().getUserName() + "将客户“" + companyNames + "”分配给您了", crmCompany.getCollarUser());
    }

    /**
     * 客户合并
     * @author 小啊刚
     * @date 2020/6/22
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void combineSave(String ids, Integer id) {
        UserInfo userInfo  = UserThreadLocal.get();
        CrmCustomer customer = getById(id);
        if(customer != null) {
            for(String crmId : ids.split(",")) {
                if(crmId.contains(id.toString())) {
                    continue;
                }

                // 联系人合并
                linkmanMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 联系记录合并
                touchMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 收货人合并
                consigneeMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 报价单合并
                quotedPriceMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 需求合并
                requirementMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 财务信息合并
                financeInfoMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 商机合并
                // 文档合并
                filesMapper.updateCrmId(Integer.valueOf(crmId), id, customer.getCrmName(), userInfo.getUserId(), userInfo.getRealName());
                // 合并完成后删除客户
                updateStatus(crmId, 1);
            }
        }
    }

    @Override
    public List<CrmCustomer> listSimpleCrmCustomerDto(Collection<String> crmNames) {
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","crm_name","crm_type","collar_user_id","is_tasking","crm_task_id");
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.ne("status",1);
        queryWrapper.ne("status",2);
        queryWrapper.in("crm_name",crmNames);
        List<CrmCustomer> list = list(queryWrapper);
        return list;
    }

    /**
     * 导入"客户"数据
     * @author 小啊刚
     * @date 2020/6/22
     */
    @Override
    public Map importData(MultipartFile file, boolean b, String[] excelFiled, String[] dbFiled, String companyType, Boolean isTask, Long taskId) throws IOException {
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        String companyName = userInfo.getCompanyName();
        Integer userId = userInfo.getUserId();
        String realName = userInfo.getRealName();
        //成功个数(新增客户个数)
        int successNum = 0;
        //客户重复个数(新增客户个数中)
        int repeatNum = 0;
        //失败个数
        int failureNum = 0;

        //失败原因
        List<String> failCauseList = new ArrayList<>();
        //失败数据
        List<List<String>> failDataList = new ArrayList<>();
        //客户数据
        List<CrmCustomer> crmCustomerList = new ArrayList<>();
        //联系人数据
        List<CrmLinkman> crmLinkmanList = new ArrayList<>();
        //需要 新增的联系人
        Set<CrmLinkman> insertLinkManSet = new LinkedSet<>();
        //符合 外呼任务的条件 联系人（线索客户_未添加外呼任务，自己的潜在客户 和 成交客户）
        Set<CrmLinkman> taskLinkManSet = new LinkedSet<>();
        //当前导入的客户map
        Map<String, CrmCustomer> crmNameMap = new HashMap();
        Map<String, List<String>> crmCellData = new HashMap<>();

        //客户自定义字段
        CrmDefineField crmField = new CrmDefineField();
        crmField.setCompanyId(companyId);
        crmField.setDataType(2);
        crmField.setSource("crm");
        List<CrmDefineField> companyFieldList = defineFieldMapper.findList(crmField);
        //联系人自定义字段
        crmField.setSource("linkMan");
        List<CrmDefineField> linkFieldList = defineFieldMapper.findList(crmField);
        boolean isExcel2003 = true;
        if (file.getOriginalFilename().matches("^.+\\.(?i)(xlsx)$")) {
            isExcel2003 = false;
        }

        //解析excel
        InputStream is = file.getInputStream();
        Workbook wb;
        if (isExcel2003) {
            wb = new HSSFWorkbook(is);
        } else {
            wb = new XSSFWorkbook(is);
        }

        Sheet sheet = wb.getSheetAt(0);
//        List<String> customerArr = crmCustomerMapper.getByCompanyId(userInfo.getCompanyId());
        Set<String> importCustmoerName = new LinkedSet<>();
        String customerNo = getCustomerNo(companyId);
        ErpNumberSet numberSet = numberSetMapper.getByCode("Customer", companyId, 0);
        int lastRowNum = sheet.getLastRowNum();
        int readNum = 0;
        for (int r = 1; r <= lastRowNum; r++) { //循环excel行读取数据
            Map<String, String> linkmanFiledMap = new HashMap(); //联系人自定义数据
            Map<String, String> crmFiledMap = new HashMap(); //客户自定义数据
            List<String> cellData = new ArrayList<>();
            Row row = sheet.getRow(r);
            if(null == row)break;
            readNum = r;
            CrmCustomer crmCustomer = new CrmCustomer();
            CrmLinkman crmLinkman = new CrmLinkman();

            for(int i=0; i<excelFiled.length; i++) {
                if(row.getCell(i) ==  null) {
                    cellData.add("");
                    continue;
                }
                row.getCell(i).setCellType(CellType.GREATER_THAN);
                //去掉空格
                String cellValue = StringUtils.normalizeSpace((row.getCell(i).getStringCellValue() + ""));
                cellData.add(cellValue);
                if(dbFiled[i] != null && !dbFiled[i].equals("")) {
                    try {
                        String[] crmFiled = dbFiled[i].split("_");
                        if (crmFiled[0].equals("link")) { //联系人数据
                            String linkField = crmFiled[1];
                            if(crmFiled[2].equals("2")) { //为2表示自定义字段
                                for (CrmDefineField cField : linkFieldList) {
                                    if (cField.getCode().equals(linkField)) {
                                        linkmanFiledMap.put(cField.getId().toString(), cellValue);
                                    }
                                }
                                continue;
                            }

                            Class linkManClass = crmLinkman.getClass();
                            Field field = linkManClass.getDeclaredField(linkField);
                            field.setAccessible(true);
//                            if(linkField.equals("gender")) {
//                                cellValue = cellValue.equals("男") ? "1" : "0";
//                            }
                            field.set(crmLinkman, cellValue);
                        } else { //客户数据
                            if(crmFiled[2].equals("2")) { //为2表示自定义字段
                                for (CrmDefineField field : companyFieldList) {
                                    if (field.getCode().equals(crmFiled[1])) {
                                        crmFiledMap.put(field.getId().toString(), cellValue);
                                    }
                                }
                                continue;
                            }
                            if(crmFiled[1].equals("areaId")) { //区域
                                crmCustomer.setAreaName(cellValue);
                                continue;
                            }
                            Class crmCompanyClass = crmCustomer.getClass();
                            Field f = crmCompanyClass.getDeclaredField(crmFiled[1]);
                            f.setAccessible(true);
                            f.set(crmCustomer, cellValue);
                            if(crmFiled[1].equals("crmName")) { //客户名称拼音码
                                if (StringUtils.isNotBlank(crmFiled[1]) && cellValue.contains("重庆")) {
                                    cellValue = cellValue.replace("重庆", "cq");
                                }
                                String py = PinyinUtils.getFirstSpell(cellValue);
                                crmCustomer.setPhonetic(py);
                            }
                        }
                    } catch (Exception e) { //自定义字段
                        e.printStackTrace();
                    }
                }
            }
            if(crmCustomer == null || StringUtils.isBlank(crmCustomer.getCrmName())) {//客户名称不能为空
                failCauseList.add("第" + (r + 1) + "行:" + "客户名称不能为空");
                failDataList.add(cellData);
                failureNum ++;
                continue;
            }
            crmCellData.put(crmCustomer.getCrmName().trim(), cellData);
            crmCustomer.setCompanyId(companyId);
            crmCustomer.setDefineFields(JSON.toJSONString(crmFiledMap));
            crmCustomerList.add(crmCustomer);
            //客户名称为空只导入联系人
            if(StringUtils.isNotBlank(crmLinkman.getName())) { //联系人名称不能为空
                crmLinkman.setDefineFields(JSON.toJSONString(linkmanFiledMap));
                List<CrmLinkman> crmCustomerLinkmanList = new ArrayList<>();
                crmCustomerLinkmanList.add(crmLinkman);
                crmCustomer.setCrmLinkmanList(crmCustomerLinkmanList);
                crmLinkman.setCompanyId(companyId);
                crmLinkman.setCrmName(crmCustomer.getCrmName().trim());
                crmLinkman.setCreateUserId(userId);
                crmLinkman.setCreateUserName(realName);
                crmLinkman.setUpdateUserId(userId);
                crmLinkman.setUpdateUserName(realName);
//                crmLinkmanList.add(crmLinkman);
            }
            importCustmoerName.add(crmCustomer.getCrmName().trim());
        }
        /** 客户名称 校验*/
        Map<String,CrmCustomer> oldCustomerMap = new HashMap<>();
        if(importCustmoerName.size() > 0){
            /*** 批量查询 客户 */
            List<CrmCustomer> oldCustomers = this.listSimpleCrmCustomerDto(importCustmoerName);
            oldCustomers.forEach(customer->oldCustomerMap.put(customer.getCrmName(),customer));
        }
        List<CrmCustomer> insertList = new ArrayList<>();
        List<CrmCustomer> updateList = new ArrayList<>();
        for (int r = 0; r < crmCustomerList.size(); r++) {
            CrmCustomer crmCustomer = crmCustomerList.get(r);
            String crmName = crmCustomer.getCrmName();
            if (companyType.contains("isCustomer")){
                crmCustomer.setIsCustomer(true);
            }
            if (companyType.contains("isSupplier")){
                crmCustomer.setIsSupplier(true);
            }
            if (companyType.contains("isOther")){
                crmCustomer.setIsOther(true);
            }
            if (companyType.contains("isFinance")){
                crmCustomer.setIsFinance(true);
            }
            /** 获取老用户*/
            CrmCustomer oldCrmCustomer = oldCustomerMap.get(crmName);
            List<CrmLinkman> crmCustomerLinkmanList = crmCustomer.getCrmLinkmanList();
            //1.当前导入的客户map
            CrmCustomer haveCrmCustomer = crmNameMap.get(crmName);
            if( null == haveCrmCustomer){
                crmNameMap.put(crmName,crmCustomer);
            }else if(null != crmCustomerLinkmanList){
                List<CrmLinkman> crmHaveCrmCustomerLinkmanList = haveCrmCustomer.getCrmLinkmanList();
                if(null == crmHaveCrmCustomerLinkmanList){
                    haveCrmCustomer.setCrmLinkmanList(crmCustomerLinkmanList);
                }else{
                    crmHaveCrmCustomerLinkmanList.addAll(crmCustomerLinkmanList);
                }
            }

            //2.客户名称不能重复
            if(null == oldCrmCustomer ) {
                List<String> cellData = crmCellData.get(crmName);
                if( null == haveCrmCustomer){
                    successNum ++;
                    //获取编码
                    customerNo = numberSetService.getCode(numberSet, customerNo);
                    if(StringUtils.isBlank(customerNo) || r == 99999) {
                        failureNum += lastRowNum - r - 1;
                        failCauseList.add("今日新增客户数已上限，不能超过9999个，请明天来导入，或联系客服人员");
                        break;
                    }
                    crmCustomer.setCrmNo(customerNo);
                    crmCustomer.setCreateUserId(userId);
                    crmCustomer.setCreateUserName(realName);
                    crmCustomer.setCompanyName(companyName);
                    crmCustomer.setCrmType(0);
                    crmCustomer.setOfficeId(userInfo.getOfficeId());
                    crmCustomer.setOfficeName(userInfo.getOfficeName());

                    insertList.add(crmCustomer);
                    if(null != crmCustomerLinkmanList){
                        insertLinkManSet.addAll(crmCustomerLinkmanList);
                        taskLinkManSet.addAll(crmCustomerLinkmanList);
                    }
                }else{
                    failureNum ++;
                    repeatNum++;
                    failDataList.add(cellData);
                    failCauseList.add("第" + (r + 2) + "行:" + "当前文档客户名称重复");
                }

            }else {
                List<String> cellData = crmCellData.get(crmName);
                failDataList.add(cellData);
                /** 校验 客户信息 是否可以 更新 **/
                /** 校验1.其他人 维护的客户 不能修改 */
                if(null != oldCrmCustomer.getCollarUserId() && !oldCrmCustomer.getCollarUserId().equals(userId)){
                    failureNum ++;
                    failCauseList.add("第" + (r + 2) + "行:" + "客户名称导入失败，其他人维护的客户");

                    continue;
                }
                /** 校验2.是否执行维护任务*/
                if(oldCrmCustomer.getCrmType() == 0 && oldCrmCustomer.getIsTasking() && !oldCrmCustomer.getCrmTaskId().equals(taskId)){
                    failureNum ++;
                    failCauseList.add("第" + (r + 2) + "行:" + "客户名称导入失败，其他人正在外呼任务");
                    continue;
                }
                if(null != crmCustomerLinkmanList){

                    if( null != taskId && null != isTask && isTask ){
                        taskLinkManSet.addAll(crmCustomerLinkmanList);
                    }

                    failCauseList.add("第" + (r + 2) + "行:" + "客户名称已存在，但联系人已导入");
                }else{
                    failCauseList.add("第" + (r + 2) + "行:" + "客户名称已存在，未导入联系人");
                }
                if(null == haveCrmCustomer){
                    crmCustomer.setId(oldCrmCustomer.getId());
                    updateList.add(crmCustomer);
                    if(null != crmCustomerLinkmanList){
                        insertLinkManSet.addAll(crmCustomerLinkmanList);
                    }
                }
            }
        }
        try {
            //批量插入数据
            if (insertList != null && insertList.size() > 0) {
                crmCustomerMapper.insertList(insertList);
                //处理联系人 和 客户 关系
                insertList.forEach(crmCustomer -> {
                    List<CrmLinkman> customerCrmLinkmanList = crmCustomer.getCrmLinkmanList();
                    if(null != customerCrmLinkmanList){
                        customerCrmLinkmanList.forEach(crmLinkman->crmLinkman.setCrmId(crmCustomer.getId().intValue()));
                    }
                });
            }
            //批量更新数据
            if(updateList != null && updateList.size() > 0){
                this.updateBatchById(updateList,100);
                //处理联系人 和 客户 关系
                updateList.forEach(crmCustomer -> {
                    List<CrmLinkman> customerCrmLinkmanList = crmCustomer.getCrmLinkmanList();
                    if(null != customerCrmLinkmanList){
                        customerCrmLinkmanList.forEach(crmLinkman->crmLinkman.setCrmId(crmCustomer.getId().intValue()));
                    }
                });
            }
            //异步处理地区
            if (crmCustomerList != null && crmCustomerList.size() > 0) {
                areaService.updateCrmArea(crmCustomerList, companyId);
            }
            //批量插入联系人
            if (insertLinkManSet != null && insertLinkManSet.size() > 0) {
                linkmanService.saveBatch(insertLinkManSet, 100);
            }
            /** 异步 新增 外呼任务明细  */
            if(null != isTask  && isTask && null != taskId && taskLinkManSet.size() > 0){
                callTaskDetailService.andCallTaskDetailFromImportCrmCustomer(userInfo,taskId,taskLinkManSet);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map result = new HashMap();
        result.put("readNum",readNum);
        result.put("insertCustomerNum",insertList.size());
        result.put("updateCustomerNum",updateList.size());
        result.put("linkManNum",insertLinkManSet.size());
        result.put("successNum", successNum);
        result.put("repeatNum", repeatNum);
        result.put("failNum", failureNum);
        result.put("excelField", excelFiled);
        result.put("failData", failDataList);
        result.put("failCause", failCauseList);
        return result;
    }

    @Override
    public Map importVendorData(MultipartFile file, boolean b, String[] excelFiled, String[] dbFiled) throws IOException {
        UserInfo userInfo = UserThreadLocal.get();
        //成功个数
        int successNum = 0;
        //失败个数
        int failureNum = 0;
        //失败原因
        List<String> failCauseList = new ArrayList<>();
        //失败数据
        List<List<String>> failDataList = new ArrayList<>();
        //客户数据
        List<CrmCustomer> crmCustomerList = new ArrayList<>();
        //客户名称标记
        Map<String, CrmCustomer> crmNameMap = new HashMap();

        //客户自定义字段
        CrmDefineField crmField = new CrmDefineField();
        crmField.setCompanyId(userInfo.getCompanyId());
        crmField.setDataType(2);
        crmField.setSource("vendor");
        List<CrmDefineField> companyFieldList = defineFieldMapper.findList(crmField);
        /******** 校验文件格式 *************/
        boolean isExcel2003 = true;
        if (file.getOriginalFilename().matches("^.+\\.(?i)(xlsx)$")) {
            isExcel2003 = false;
        }
        //解析excel
        InputStream is = file.getInputStream();
        Workbook wb;
        if (isExcel2003) {
            wb = new HSSFWorkbook(is);
        } else {
            wb = new XSSFWorkbook(is);
        }
        Sheet sheet = wb.getSheetAt(0);

        List<String> customerArr = crmCustomerMapper.getByCompanyId(userInfo.getCompanyId());
        String customerNo = getCustomerNo(userInfo.getCompanyId());
        ErpNumberSet numberSet = numberSetMapper.getByCode("Customer", userInfo.getCompanyId(), 0);
        for (int r = 1; r <= sheet.getLastRowNum(); r++) { //循环excel行读取数据
            Map<String, String> crmFiledMap = new HashMap(); //客户自定义数据
            List<String> cellData = new ArrayList<>();
            Row row = sheet.getRow(r);
            CrmCustomer crmCustomer = new CrmCustomer();
            for(int i=0; i<excelFiled.length; i++) {
                if(row.getCell(i) ==  null) {
                    cellData.add("");
                    continue;
                }
                row.getCell(i).setCellType(CellType.GREATER_THAN);
                String cellValue = (row.getCell(i).getStringCellValue() + "").trim();
                cellData.add(cellValue);
                if(dbFiled[i] != null && !dbFiled[i].equals("")) {
                    try {
                        String[] crmFiled = dbFiled[i].split("_");
                        if(crmFiled[2].equals("2")) { //为2表示自定义字段
                            for (CrmDefineField field : companyFieldList) {
                                if (field.getCode().equals(crmFiled[1])) {
                                    crmFiledMap.put(field.getId().toString(), cellValue);
                                }
                            }
                            continue;
                        }

                        if(crmFiled[1].equals("areaId")) { //区域
                            crmCustomer.setAreaName(cellValue);
                            continue;
                        }

                        Class crmCompanyClass = crmCustomer.getClass();
                        Field f = crmCompanyClass.getDeclaredField(crmFiled[1]);
                        f.setAccessible(true);
                        f.set(crmCustomer, cellValue);
                        if(crmFiled[1].equals("crmName")) { //客户名称拼音码
                            if (StringUtils.isNotBlank(crmFiled[1]) && cellValue.contains("重庆")) {
                                cellValue = cellValue.replace("重庆", "cq");
                            }
                            String py = PinyinUtils.getFirstSpell(cellValue);
                            crmCustomer.setPhonetic(py);
                        }
                    } catch (Exception e) { //自定义字段
                        e.printStackTrace();
                    }
                }
            }

            if(crmCustomer == null || StringUtils.isBlank(crmCustomer.getCrmName())) {//客户名称不能为空
                failCauseList.add("第" + (r + 1) + "行:" + "单位名称不能为空");
                failDataList.add(cellData);
                failureNum ++;
                continue;
            }

            crmCustomer.setCompanyId(userInfo.getCompanyId());
            if(!customerArr.contains(crmCustomer.getCrmName().trim()) && crmNameMap.get(crmCustomer.getCrmName().trim()) == null) {//客户名称不能重复
                crmNameMap.put(crmCustomer.getCrmName().trim(), crmCustomer);
                crmCustomer.setCreateUserId(userInfo.getUserId());
                crmCustomer.setCreateUserName(userInfo.getRealName());
                crmCustomer.setCompanyName(userInfo.getCompanyName());
                crmCustomer.setCrmType(0);
                crmCustomer.setOfficeId(userInfo.getOfficeId());
                crmCustomer.setOfficeName(userInfo.getOfficeName());
                crmCustomer.setDefineFields(JSON.toJSONString(crmFiledMap));

                if( r > 1) {
                    customerNo = numberSetService.getCode(numberSet, customerNo);
                }

                if(StringUtils.isBlank(customerNo) || r == 99999) {
                    failureNum += sheet.getLastRowNum() - r;
                    failCauseList.add("今日新增客户数已上限，不能超过9999个，请明天来导入，或联系客服人员");
                    break;
                }

                crmCustomer.setCrmNo(customerNo);
                crmCustomer.setIsSupplier(true);
                crmCustomer.setIsFinance(true);
                crmCustomerList.add(crmCustomer);
                successNum ++;

            }else {
                failCauseList.add("第" + (r + 1) + "行:" + "单位名称已存在");
                failDataList.add(cellData);
                failureNum ++;
            }
        }

        try {
            if (crmCustomerList != null && crmCustomerList.size() > 0) { //批量插入数据
                crmCustomerMapper.insertList(crmCustomerList);
                //异步处理地区
                areaService.updateCrmArea(crmCustomerList, userInfo.getCompanyId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        Map result = new HashMap();
        result.put("failNum", failureNum);
        result.put("successNum", successNum);
        result.put("excelField", excelFiled);
        result.put("failData", failDataList);
        result.put("failCause", failCauseList);
        return result;
    }

    /**
     * 异步处理客户地区
     * @author 小啊刚
     * @date 2020/7/6
     */
//    @Async
//    public void updateCrmArea(List<CrmCustomer> customerList, Integer companyId) {
//        for(CrmCustomer customer : customerList) {
//            if(StringUtils.isNotBlank(customer.getAreaName())) {
//                SysArea area = areaMapper.getAreaByTreeNames(customer.getAreaName(), companyId);
//                if(area != null) {
//                    customer.setAreaId(area.getId().intValue());
//                    crmCustomerMapper.updateById(customer);
//                }
//            }
//        }
//    }

    @Override
    public List<Map<String, String>> getCrmImportFiled() {
        UserInfo userInfo = UserThreadLocal.get();
        List<Map<String, String>> codeList = defineFieldMapper.getCrmImportFiled(userInfo.getCompanyId());
        List<Map<String, String>> dataCodeList = new ArrayList<>();
        for(Map<String, String> data : codeList) {
            if(("phonetic,collarUserId,shareType,officeName,lastTouchDate,nextTouchDate,releaseTime,collarTime" +
                    ",releaseUserId,createUserId,createDate,lastCollarTime,lastCollarUserId,status").contains(data.get("key").split("_")[1])) {
                continue;
            }
            dataCodeList.add(data);
        }
        return dataCodeList;
    }

    @Override
    public void updateCrmCode(String currentCode) {
        UserInfo userInfo = UserThreadLocal.get();
        crmCustomerMapper.updateCode(currentCode, userInfo.getCompanyId());
    }

    @Override
    @Async
    public void updateUserRealName(Long id, String realName) {
        //修改所属人
        crmCustomerMapper.updateCollarName(id, realName);
        //修改上次领用人
        crmCustomerMapper.updateLastCollarUserName(id, realName);
        //修改释放人
        crmCustomerMapper.releaseUserName(id, realName);
        //修改员工姓名
        sysUserMapper.updateEmpName(id, realName);
        //修改业务人员
        touchMapper.updateSalesMan(id, realName);
        //修改
        String[] tables = {"pub_customer", "crm_consignee", "crm_business", "crm_requirement", "crm_files", "crm_touch", "crm_linkman", "crm_finance_info"};
        for(int i=0; i<tables.length; i++) {
            //修改创建人
            crmCustomerMapper.updateCreateName(tables[i], id, realName);
            //修改修改人
            crmCustomerMapper.updateUpdateName(tables[i], id, realName);
        }

    }

    @Override
    public Page<Map> followAnalysis(Page page, CrmFollowAnalysis analysis) {
        UserInfo userInfo = UserThreadLocal.get();
        analysis.setCompanyId(userInfo.getCompanyId());
        return crmCustomerMapper.followAnalysis(page, analysis, userInfo);
    }

    @Override
    public Map crmAnalysisTable(CrmFollowAnalysis analysis) {
        UserInfo userInfo = UserThreadLocal.get();
        analysis.setCompanyId(userInfo.getCompanyId());
        String[] filedId = {"office_id", "collar_user_id", "area_id", "crm_grade", "industry", "enterprise_scale", "crm_source"};
        String[] filedName = {"office_name", "collar_user_name", "area_name", "crm_grade", "industry", "enterprise_scale", "crm_source"};
        analysis.setFiledId(filedId[analysis.getAnalysisType()]);
        analysis.setFiledName(filedName[analysis.getAnalysisType()]);
        return crmCustomerMapper.crmAnalysisTable(analysis, userInfo);
    }

    /***************** 客户——财务 开始 *****************/
    @Override
    public Page<CrmCustomerFinanceVo> pageCrmCustomerFinanceVo(Page page, CrmCustomerFinanceDto crmCustomerFinanceDto) {
        UserInfo userInfo = UserThreadLocal.get();
        crmCustomerFinanceDto.setCompanyId(userInfo.getCompanyId());
        Page<CrmCustomerFinanceVo> crmCustomerFinanceVoPage = baseMapper.pageCrmCustomerFinanceVo(page, crmCustomerFinanceDto);
        return crmCustomerFinanceVoPage;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveFromFinance(CrmCustomerFinanceVo crmCustomerFinanceVo) {
        LocalDateTime now = LocalDateTime.now();
        UserInfo userInfo = UserThreadLocal.get();
        Long id = crmCustomerFinanceVo.getId();
        CrmCustomer oldCrmCustomer = null;
        CrmFinanceInfo crmFinanceInfo = null;

        //编辑 客户
        if(null != id){
            oldCrmCustomer = getById(id);
            if ( null == oldCrmCustomer)throw new NuoNiuException("参数错误（ID）,查询不到客户信息");
        }

        //新增
        else{
            //通过名称 查找是否已存在 该客户
            oldCrmCustomer = getByName(crmCustomerFinanceVo.getCrmName());
        }
        if( null == oldCrmCustomer ){
            oldCrmCustomer = new CrmCustomer();
            oldCrmCustomer.setCreateDate(now);
            oldCrmCustomer.setCreateUserId(userInfo.getUserId());
            oldCrmCustomer.setCreateUserName(userInfo.getRealName());
            oldCrmCustomer.setCompanyId(userInfo.getCompanyId());
            oldCrmCustomer.setIsRelease(true);
            oldCrmCustomer.setCrmType(0); //默认 线索客户

            // 初始化客户编号
            String customerNo = getCustomerNo(userInfo.getCompanyId());
            if (StringUtils.isEmpty(customerNo)) {
               throw new NuoNiuException("今日新增客户数不能超过9999个");
            }

            oldCrmCustomer.setCrmNo(customerNo);
            if (StringUtils.isEmpty(oldCrmCustomer.getPhonetic())) {
                ChineseCharToEnUtil cte = new ChineseCharToEnUtil();
                oldCrmCustomer.setPhonetic(cte.getAllFirstLetter(oldCrmCustomer.getCrmName()));
            }
        }

        BeanUtils.copyProperties(crmCustomerFinanceVo,oldCrmCustomer,"crmNo");
        oldCrmCustomer.setStatus(0);
        oldCrmCustomer.setIsFinance(true);
        oldCrmCustomer.setIsCustomer(true);
        oldCrmCustomer.setUpdateDate(now);
        oldCrmCustomer.setUpdateUserId(userInfo.getUserId());
        oldCrmCustomer.setUpdateUserName(userInfo.getRealName());
        //保存 客户信息
        saveOrUpdate(oldCrmCustomer);
        //查询当前客户 是否已经存在 财务信息
        crmFinanceInfo = crmFinanceInfoService.getByCrmId(oldCrmCustomer.getId().intValue());
        if(null == crmFinanceInfo ){
            crmFinanceInfo = new CrmFinanceInfo();
            crmFinanceInfo.setCreateDate(now);
            crmFinanceInfo.setCreateUserId(userInfo.getUserId());
            crmFinanceInfo.setCreateUserName(userInfo.getRealName());
        }

        BeanUtils.copyProperties(crmCustomerFinanceVo,crmFinanceInfo,"id");
        crmFinanceInfo.setCrmId(oldCrmCustomer.getId().intValue());
        crmFinanceInfo.setStatus(0);
        crmFinanceInfo.setUpdateDate(now);
        crmFinanceInfo.setUpdateUserId(userInfo.getUserId());
        crmFinanceInfo.setUpdateUserName(userInfo.getRealName());
        //保存 财务信息
        crmFinanceInfoService.saveOrUpdate(crmFinanceInfo);
    }

    @Override
    public void checkForFinance(Integer id) {
        if (null == id)throw new NuoNiuException("参数错误");
        CrmCustomer crmCustomer = getById(id);
        if (null == crmCustomer)throw new NuoNiuException("参数错误");
        if(!crmCustomer.getIsFinance()){
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("id",id);
            updateWrapper.set("is_finance",1);
            update(updateWrapper);
        }
    }

    @Override
    public void removeFromFinance(Long... ids) {
        if (null == ids)throw new NuoNiuException("参数错误");
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.in("id",ids);
        updateWrapper.set("is_finance",0);
        update(updateWrapper);
    }

//    @Override
//    public void removeFromFinance(Integer id) {
//        if (null == id)throw new NuoNiuException("参数错误");
//        UpdateWrapper updateWrapper = new UpdateWrapper();
//        updateWrapper.eq("id",id);
//        updateWrapper.set("is_finance",0);
//        update(updateWrapper);
//    }

    @Override
    public Long saveCustomer(CrmCustomerDto crmCustomerDto) {
        Boolean isCheck = crmCustomerDto.getIsCheck();
        CrmCustomer crmCustomer = new CrmCustomer();
        BeanUtils.copyProperties(crmCustomerDto, crmCustomer);
        UserInfo userInfo = UserThreadLocal.get();
        if (crmCustomer.getId() == null) {
            crmCustomer.setCompanyId(userInfo.getCompanyId());
            crmCustomer.setCompanyName(userInfo.getCompanyName());
            crmCustomer.setCreateUserId(userInfo.getUserId());
            crmCustomer.setCreateUserName(userInfo.getRealName());
            crmCustomer.setOfficeName(userInfo.getOfficeName());
            crmCustomer.setOfficeId(userInfo.getOfficeId());
            crmCustomer.setIsCustomer(true);
            CrmCustomer customer = findByName(crmCustomer.getCompanyId(), crmCustomer.getCrmName().trim());
            if (customer != null) {
                Boolean isCustomer = customer.getIsCustomer();
                //是否 校验
                if(isCheck && isCustomer != null && isCustomer){
                    String message = checkRecord(1,customer);
                    throw new NuoNiuException(message);
                }
                crmCustomer.setId(customer.getId());
            }else{
                // 初始化客户编号
                String customerNo = getCustomerNo(userInfo.getCompanyId());
                if (StringUtils.isEmpty(customerNo)) {
                    throw new NuoNiuException("今日新增客户数不能超过9999个");
                }

                crmCustomer.setCrmNo(customerNo);
                if (StringUtils.isEmpty(crmCustomer.getPhonetic())) {
                    ChineseCharToEnUtil cte = new ChineseCharToEnUtil();
                    crmCustomer.setPhonetic(cte.getAllFirstLetter(crmCustomer.getCrmName()));
                }

                // 潜在客户新增或者成交客户新增 默认所属人为当前创建人
                if (null != crmCustomer.getCrmType() && crmCustomer.getCrmType() != 0) {
                    crmCustomer.setCollarUserId(userInfo.getUserId());
                    crmCustomer.setCollarUserName(userInfo.getRealName());
                    crmCustomer.setCollarTime(LocalDateTime.now());
                }
            }
        }

        crmCustomer.setUpdateDate(LocalDateTime.now());
        crmCustomer.setUpdateUserId(userInfo.getUserId());
        crmCustomer.setUpdateUserName(userInfo.getRealName());

        if(null != crmCustomer.getAreaId()){
            HashMap<String, String> areaHashMap = sysAreaService.findAreaTreeNamesById(crmCustomer.getAreaId(), userInfo.getCompanyId());
            if(areaHashMap != null) {
                crmCustomer.setAreaName(areaHashMap.get("treeName"));
                crmCustomer.setAreaTreeCodes(areaHashMap.get("areaTreeCodes"));
            }
        }

        // 保存客户
        Boolean result = this.saveOrUpdate(crmCustomer);
        if(!result) {
            throw new NuoNiuException("保存失败，请联系管理员！");
        }
        return crmCustomer.getId();
    }

    /**
     *
     * @param response
     * @param source
     * #  	crm   				客户
     * #  	vendor 				供应商
     * #	company				往来单位
     * # 	linkMan    		    联系人
     * #	touch 				联系记录
     * #	business			商机
     * #	finance 			财务
     * #	financeCrm		    客户档案
     */
    @Override
    public void importTemplate(HttpServletResponse response,String source) {
        //填充模版数据
        String[] data = {"例*上海XXXX有限公司", "客户", "电话联系", "上海市/浦东新区", "科技研究", "xxx备注", "上海市浦东新区泸南路", "13320372373", "774578770@qq.com", "啊刚", "www.bai.com", "50-100", "C", "1000000"};
        String[] data2 = {};
        String fileName = "导入客户资料模板.xls";
        List<String> names = new ArrayList<String>();
        if(StringUtils.isBlank(source))throw new NuoNiuException("参数错误");
        switch (source){
            case "crm":
                //查询客户自定义字段
                List<CrmDefineField> defineFields = defineFieldService.getCrmDefineFieldList("crm");
                for(CrmDefineField field : defineFields) {
                    if(field.getOnOff()) {
                        if(("phonetic,collarUserId,shareType,officeId,lastTouchDate,nextTouchDate,releaseTime,collarTime" +
                                ",releaseUserId,createUserId,createDate,lastCollarTime,lastCollarUserId,status").contains(field.getCode())) {
                            continue;
                        }
                        names.add(field.getName());
                    }
                }
                //将如下信息放到自定义字段后面
                names.add("联系人.姓名");
                names.add("联系人.性别");
                names.add("联系人.部门");
                names.add("联系人.职务");
                names.add("联系人.手机号码");
                names.add("联系人.办公电话");
                names.add("联系人.电子邮件");
                break;
            //供应商
            case "vendor":
                data = data2;
                fileName = "导入供应商资料模板.xls";
                //查询客户自定义字段
                List<CrmDefineField> vendorDefineFields = defineFieldService.getCrmDefineFieldList("vendor");
                for(CrmDefineField field : vendorDefineFields) {
                    if(field.getOnOff()) {
                        if(("createUserId,createDate,status").contains(field.getCode())) {
                            continue;
                        }
                        names.add(field.getName());
                    }
                }
                break;
            //供应链 -- 客户档案
            case "financeCrm":
                data = data2;
                fileName = "导入客户档案模板.xls";
                //查询客户自定义字段
                List<CrmDefineField> crmDefineFields = defineFieldService.getCrmDefineFieldList("financeCrm");
                for(CrmDefineField field : crmDefineFields) {
                    if(field.getOnOff()) {
                        if(("createUserId,createDate,status").contains(field.getCode())) {
                            continue;
                        }
                        names.add(field.getName());
                    }
                }
                break;
        }
        Object[] title = names.toArray();
        ExcelUtils.export(title,  fileName, data, response);
    }


//    /**************************************  erp -- 客户档案 导入、导出 -- Start ***********************************************/
//    @Override
//    public void downloadImportTemplate(HttpServletResponse response) {
//        //填充模版数据
//        String fileName = "导入客户资料模板";
//        String[] data = {"重庆四班科技有限公司", "91500112MA7D7MN22R","电话联系", "信息传输、软件和信息技术服务业","重庆市/渝北区", "1-49人", "1000万","岳老师",  "023-68888995","13918806563", "584418600@qq.com", "https://sibanyun.cn/", "重庆市渝北区仙桃街道数据谷中路107号", "备注**"};
//        Object[] title = {"客户名称", "统一代码", "客户来源", "所属行业", "所属地区", "企业规模", "注册资本", "法定代表", "电话号码", "手机号码", "电子邮箱", "公司网址", "联系地址", "备注"};
//        ExcelUtils.export(title,  fileName, data, response);
//    }
//    @Override
//    public Map erpCrmImportData(MultipartFile file) throws IOException, NoSuchFieldException, IllegalAccessException {
//        UserInfo userInfo = UserThreadLocal.get();
//        //成功个数
//        int successNum = 0;
//        //失败个数
//        int failureNum = 0;
//        //失败原因
//        List<String> failCauseList = new ArrayList<>();
//        //失败数据
//        List<List<String>> failDataList = new ArrayList<>();
//        //客户数据
//        List<CrmCustomer> crmCustomerList = new ArrayList<>();
//        //财务数据
//        List<CrmFinanceInfo> crmFinanceInfoList = new ArrayList<>();
//
//        //客户名称标记
//        Map<String, CrmCustomer> crmNameMap = new HashMap();
//        String[] customerArr = crmCustomerMapper.getByCompanyId(userInfo.getCompanyId());
//        String[] crmFiled = {"crmName", "uscCode", "crmSource", "industry", "areaName","enterpriseScale", "registerCapital","legalPerson","phone","mobile","email","url","street","remarks"};
////        String[] crmFiled = {"crmName", "industry", "areaName", "legalPerson", "enterpriseScale", "registerCapital", "taxNature", "companyNumber", "address", "openingBank", "bankAccount", "phone", "electronicInvoiceEmail", "electronicInvoicePhone", "remarks"};
//        String customerNo = getCustomerNo(userInfo.getCompanyId());
//        ErpNumberSet numberSet = numberSetMapper.getByCode("Customer", userInfo.getCompanyId(), 0);
//        Workbook wb;
//        boolean isExcel2003 = true;
//
//        if (file.getOriginalFilename().matches("^.+\\.(?i)(xlsx)$")) {
//            isExcel2003 = false;
//        }
//
//        //解析excel
//        InputStream is = file.getInputStream();
//        if (isExcel2003) {
//            wb = new HSSFWorkbook(is);
//        } else {
//            wb = new XSSFWorkbook(is);
//        }
//
//        Sheet sheet = wb.getSheetAt(0);
//        for (int r = 1; r <= sheet.getLastRowNum(); r++) { //循环excel行读取数据
//            if( r > 1) {
//                customerNo = numberSetService.getCode(numberSet, customerNo);
//            }
//
//            if(StringUtils.isBlank(customerNo) || r == 99999) {
//                failureNum += sheet.getLastRowNum() - r;
//                failCauseList.add("今日新增客户数已上限，不能超过9999个，请明天来导入，或联系客服人员");
//                break;
//            }
//
//            List<String> cellData = new ArrayList<>();
//            CrmCustomer crmCustomer = new CrmCustomer(); //客户数据
//            CrmFinanceInfo financeInfo = new CrmFinanceInfo(); //客户财务信息
//
//            Row row = sheet.getRow(r);
//            for(int i=0; i<crmFiled.length; i++) {
//                if (row.getCell(i) == null) {
//                    cellData.add("");
//                    continue;
//                }
//
//                row.getCell(i).setCellType(CellType.GREATER_THAN);
//                String cellValue = (row.getCell(i).getStringCellValue() + "").trim();
//                cellData.add(cellValue);
//
////                if(i < 6) { //保存客户数据
//                    if(crmFiled[1].equals("areaName")) { //区域
//                        //
//                        crmCustomer.setAreaName(cellValue);
//                        continue;
//                    }
//
//                    if(crmFiled[i].equals("crmName")) { //客户名称拼音码
//                        crmCustomer.setCrmName(cellValue);
//                        if (StringUtils.isNotBlank(crmFiled[1]) && cellValue.contains("重庆")) {
//                            cellValue = cellValue.replace("重庆", "cq");
//                        }
//                        String py = PinyinUtils.getFirstSpell(cellValue);
//                        crmCustomer.setPhonetic(py);
//                        crmCustomer.setCrmSimpleName(py);
//                        continue;
//                    }
//
//                    Class crmCompanyClass = crmCustomer.getClass();
//                    Field f = crmCompanyClass.getDeclaredField(crmFiled[i]);
//                    f.setAccessible(true);
//                    f.set(crmCustomer, cellValue);
////                }else { //保存财务数据
////                    Class financeInfoClass = financeInfo.getClass();
////                    Field f = financeInfoClass.getDeclaredField(crmFiled[i]);
////                    f.setAccessible(true);
////                    f.set(financeInfo, cellValue);
////                }
//            }
//
//            if(crmCustomer == null || StringUtils.isBlank(crmCustomer.getCrmName())) {//客户名称不能为空
//                failCauseList.add("第" + (r + 1) + "行:" + "客户名称不能为空");
//                failDataList.add(cellData);
//                failureNum ++;
//                continue;
//            }
//
//            //保存客户
//            crmCustomer.setCompanyId(userInfo.getCompanyId());
//            if(!Arrays.asList(customerArr).contains(crmCustomer.getCrmName().trim()) && crmNameMap.get(crmCustomer.getCrmName().trim()) == null) {
//                crmNameMap.put(crmCustomer.getCrmName().trim(), crmCustomer);
//                crmCustomer.setCrmNo(customerNo);
//                crmCustomer.setCreateUserId(userInfo.getUserId());
//                crmCustomer.setCreateUserName(userInfo.getRealName());
//                crmCustomer.setCompanyName(userInfo.getCompanyName());
//                crmCustomer.setCrmType(0);
//                crmCustomer.setIsFinance(true);
//                crmCustomer.setIsCustomer(true);
//                crmCustomerList.add(crmCustomer);
//
//                if(financeInfo != null) {
//                    financeInfo.setCompanyId(userInfo.getCompanyId());
//                    financeInfo.setCreateUserId(userInfo.getUserId());
//                    financeInfo.setCreateUserName(userInfo.getRealName());
//                    financeInfo.setCrmName(crmCustomer.getCrmName());
//                    crmFinanceInfoList.add(financeInfo);
//                }
//
//                successNum++;
//            } else {
//                failCauseList.add("第" + (r + 1) + "行:" + "客户名称已存在");
//                failureNum ++;
//                failDataList.add(cellData);
//                continue;
//            }
//        }
//
//        if (crmCustomerList != null && crmCustomerList.size() > 0) { //批量插入数据
//            this.saveBatch(crmCustomerList, crmCustomerList.size());
//            //异步处理地区
//            areaService.updateCrmArea(crmCustomerList, userInfo.getCompanyId());
//        }
//
//        //批量插入财务
//        if (crmFinanceInfoList != null && crmFinanceInfoList.size() > 0) {
//            for (CrmFinanceInfo crmFinanceInfo : crmFinanceInfoList) {
//                if (crmFinanceInfo.getCrmId() == null && StringUtils.isNotBlank(crmFinanceInfo.getCrmName())) {
//                    if (crmNameMap.get(crmFinanceInfo.getCrmName()).getId() != null && crmNameMap.get(crmFinanceInfo.getCrmName()) != null) {
//                        crmFinanceInfo.setCrmId(crmNameMap.get(crmFinanceInfo.getCrmName()).getId().intValue());
//                    } else {
//                        CrmCustomer customer = crmCustomerMapper.findByName(userInfo.getCompanyId(), crmFinanceInfo.getCrmName());
//                        if (customer != null) {
//                            crmFinanceInfo.setCrmId(customer.getId().intValue());
//                        }
//                    }
//                }
//            }
//            crmFinanceInfoService.saveBatch(crmFinanceInfoList, crmFinanceInfoList.size());
//        }
//        Object[] excelField = {"客户名称", "统一代码", "客户来源", "所属行业", "所属地区", "企业规模", "注册资本", "法定代表", "电话号码", "手机号码", "电子邮箱", "公司网址", "联系地址", "备注"};
////        String[] excelField = {"客户名称", "所属行业", "所属地区", "法定代表", "企业规模", "注册资本", "纳税性质", "统一社会代码", "地址", "开户银行", "银行账户", "联系人电话", "电子发票接收邮件", "电子发票接收手机", "备注"};
//        Map result = new HashMap();
//        result.put("failNum", failureNum);
//        result.put("successNum", successNum);
//        result.put("failCause", failCauseList);
//        result.put("failData", failDataList);
//        result.put("excelField", excelField);
//        return result;
//    }
//
//    @Override
//    public void downloadErpCrmData(HttpServletResponse response) {
//        UserInfo userInfo = UserThreadLocal.get();
//        String[] crmField = {"crm_name", "usc_code", "crm_source", "industry", "areaName","enterprise_scale", "register_capital","legal_person","phone","mobile","email","url","street","remarks"};
//        Object[] title = {"客户名称", "统一代码", "客户来源", "所属行业", "所属地区", "企业规模", "注册资本", "法定代表", "电话号码", "手机号码", "电子邮箱", "公司网址", "联系地址", "备注"};
//        List<HashMap<String, Object>> crmList = baseMapper.getErpList(userInfo.getCompanyId());
//        ExcelUtils.exportData(title, "客户导入", crmList, crmField, response);
//    }
//    /**************************************  erp -- 客户档案 导入、导出 -- END ***********************************************/


    @Override
    public CrmCustomer checkName(String crmName, Integer companyId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("company_id", companyId);
        wrapper.eq("crm_name", crmName);
        wrapper.last("LIMIT 1");
        return getOne(wrapper);
    }

    @Override
    public void updateCallTaskState(UserInfo userInfo,Set<Long> crmIds, Integer taskId, boolean isTasking) {
        log.info("更新 客户外呼任务状态，crmIds:{},taskId;{},isTasking:{}",JSON.toJSONString(crmIds),taskId,isTasking);
        if(crmIds.size() == 0)return;
        Set<Long> isTaskingCrmIds = baseMapper.listCrmIdFromTaskIngLinkMan(userInfo.getCompanyId(), crmIds, taskId);
        if(isTaskingCrmIds.size() > 0){
            crmIds.removeAll(isTaskingCrmIds);
        }
        if(crmIds.size()  == 0)return;
        UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",crmIds);
        updateWrapper.eq("company_id",userInfo.getCompanyId());
        if(isTasking){
            updateWrapper.set("crm_task_id",taskId);
            updateWrapper.set("is_tasking",1);
            updateWrapper.eq("crm_task_id",0);
            updateWrapper.eq("is_tasking",0);
        }else{
            updateWrapper.set("crm_task_id",0);
            updateWrapper.set("is_tasking",0);
            updateWrapper.eq("crm_task_id",taskId);
            updateWrapper.eq("is_tasking",1);
        }
        this.update(updateWrapper);
    }

    @Override
    public void updateCallTaskStateByCloseTask(UserInfo userInfo, List<Long> taskIds) {
        log.info("清除 客户外呼任务状态(指定任务)，taskIds;{}",JSON.toJSONString(taskIds));
        if(taskIds.size() == 0)return;
        UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("company_id",userInfo.getCompanyId());
        updateWrapper.set("crm_task_id",0);
        updateWrapper.set("is_tasking",0);
        updateWrapper.in("crm_task_id",taskIds);
//        updateWrapper.eq("is_tasking",1);
        this.update(updateWrapper);
    }


    /*******************  供应商管理 **************************/

    /**
     * 保存 供应商
     * @param crmCustomerDto
     */
    @Override
    public void saveVendor(CrmCustomerDto crmCustomerDto) {
        CrmCustomer crmCustomer = new CrmCustomer();
        BeanUtils.copyProperties(crmCustomerDto, crmCustomer);
        UserInfo userInfo = UserThreadLocal.get();
        LocalDateTime now = LocalDateTime.now();
        //查询
        Long id = crmCustomer.getId();
        if(null == id){
            CrmCustomer customer = getByName(crmCustomer.getCrmName());
            if(null != customer){
                crmCustomer.setId(customer.getId());
            }else{
                crmCustomer.setCreateDate(now);
                crmCustomer.setCreateUserId(userInfo.getUserId());
                crmCustomer.setCreateUserName(userInfo.getRealName());
//                String message = checkRecord(2,customer);
//            if(StringUtils.isNotBlank(message))throw new NuoNiuException(message);
                crmCustomer.setCompanyId(userInfo.getCompanyId());
                crmCustomer.setCompanyName(userInfo.getCompanyName());
                // 初始化客户编号
                String customerNo = getCustomerNo(userInfo.getCompanyId());
                if (StringUtils.isEmpty(customerNo)) {
                    throw new NuoNiuException("今日新增供应商数不能超过9999个");
                }

                crmCustomer.setCrmNo(customerNo);
                if (StringUtils.isEmpty(crmCustomer.getPhonetic())) {
                    ChineseCharToEnUtil cte = new ChineseCharToEnUtil();
                    crmCustomer.setPhonetic(cte.getAllFirstLetter(crmCustomer.getCrmName()));
                }
            }
//

        }

        crmCustomer.setUpdateDate(now);
        crmCustomer.setUpdateUserId(userInfo.getUserId());
        crmCustomer.setUpdateUserName(userInfo.getRealName());
        crmCustomer.setIsFinance(true);
        crmCustomer.setIsSupplier(true);
        //设置 不可更改的字段
        crmCustomer.setIsOther(null);
        crmCustomer.setIsCustomer(null);
        crmCustomer.setIsRelease(null);
        saveOrUpdate(crmCustomer);
    }

    /**
     * 批量 移除 供应商 属性
     * @param ids
     */
    @Override
    public void removeVendor(String ids) {
        UserInfo userInfo = UserThreadLocal.get();
        String[] idArr = ids.split(",");
        for(String id : idArr) {
            UpdateWrapper<CrmCustomer> updateWrapper = new UpdateWrapper<>();
            CrmCustomer customer = this.getById(id);
            if(customer.getIsCustomer() == null || !customer.getIsCustomer()) {
                updateWrapper.set("status", 2);
            }

            updateWrapper.set("is_supplier", 0);
            updateWrapper.eq("company_id", userInfo.getCompanyId());
            updateWrapper.eq("id", id);
            update(updateWrapper);
        }
    }

    /**
     * 根据ID 获取当前租户的客户( 不校验权限 )
     * @param id
     * @return
     */
    @Override
    public CrmCustomer getById(Long id, Integer companyId) {
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id", companyId);
        queryWrapper.eq("id", id);
        queryWrapper.last("LIMIT 1");
        return getOne(queryWrapper,true);
    }

    @Override
    @Async
    public void contactCustomerNotice() {
        List<SysMsg> msgList = new ArrayList<>();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        List<CrmTouch> touchList = touchMapper.getListByNextTouchDate();
        for(CrmTouch touch : touchList) {
            CrmCustomer customer = this.getById(touch.getCrmId());
            if(customer != null) {
                SysUser adminUser = userService.getUserAdmin(touch.getCompanyId());
                SysMsg msg = new SysMsg();
                msg.setType(1);
                msg.setCompanyId(touch.getCompanyId());
                msg.setUserId(touch.getSalesManId());
                msg.setUserName(touch.getSalesManName());
                msg.setTitle("客户下次联系提醒");
                msg.setContent(df.format(touch.getNextTouchDate()) + "需要联系'" + touch.getCrmName() + "'客户,请前往查看！");
                msg.setVoucherId(touch.getCrmId().longValue());
                if(customer.getCrmType().equals(0)) {
                    msg.setMenuHref("/crm/customer/list");
                } else if(customer.getCrmType().equals(1)) {
                    msg.setMenuHref("/crm/customer/potential");
                } else {
                    msg.setMenuHref("/views/crm/customer/deals");
                }

                //推送业务员
                msgList.add(msg);
                //推送管理员
                if(adminUser != null && !(adminUser.getId().equals(touch.getSalesManId().longValue()))) {
                    msg.setUserId(adminUser.getId().intValue());
                    msg.setUserName(adminUser.getRealName());
                    msgList.add(msg);
                }
            }
        }
        msgService.saveBatch(msgList);
    }
}
